home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfslib / seg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-17  |  24.8 KB  |  982 lines

  1. /* 
  2.  * seg.c --
  3.  *
  4.  *    Routines for accessing LFS  segments from a user level program
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.3 90/01/12 12:03:36 douglis Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include "lfslib.h"
  21. #include "lfslibInt.h"
  22. #ifdef _HAS_PROTOTYPES
  23. #include <varargs.h>
  24. #include <sys/types.h>
  25. #endif /* _HAS_PROTOTYPES */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <sys/file.h>
  29. #include <unistd.h>
  30. #include <bstring.h>
  31.  
  32.  
  33. /*
  34.  *----------------------------------------------------------------------
  35.  *
  36.  * LfsSegInit --
  37.  *
  38.  *    Initialize a LfsSeg structure to allow access to an LFS segment.
  39.  *    Supports only one segment at a time.
  40.  *
  41.  * Results:
  42.  *    A pointer to a LfsSeg structure
  43.  *
  44.  * Side effects:
  45.  *    None.
  46.  *
  47.  *----------------------------------------------------------------------
  48.  */
  49.  
  50. LfsSeg *
  51. LfsSegInit(lfsPtr, segNumber)
  52.     Lfs    *lfsPtr;    /* File system. */
  53.     int    segNumber;    /* Segment number to operate on. */
  54. {
  55.  
  56.     LfsSeg *segPtr;
  57.  
  58.     segPtr = (LfsSeg *) calloc(1, sizeof(LfsSeg));
  59.  
  60.     segPtr->lfsPtr = lfsPtr;
  61.     segPtr->segNo = segNumber;
  62.     return segPtr;
  63. }
  64.  
  65.  
  66. /*
  67.  *----------------------------------------------------------------------
  68.  *
  69.  * LfsSegStartAddr --
  70.  *
  71.  *    REturn the staring address of the specified LfsSeg on disk.
  72.  *
  73.  * Results:
  74.  *    A disk block address
  75.  *
  76.  * Side effects:
  77.  *    None.
  78.  *
  79.  *----------------------------------------------------------------------
  80.  */
  81.  
  82. int
  83. LfsSegStartAddr(segPtr)
  84.     LfsSeg    *segPtr;
  85. {
  86.     return  segPtr->segNo * LfsSegSizeInBlocks(segPtr->lfsPtr) + 
  87.             segPtr->lfsPtr->superBlock.hdr.logStartOffset;
  88. }
  89.  
  90.  
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * LfsSegFetchBlock --
  95.  *
  96.  *    Fetch blocks from an LFS segment on disk.
  97.  *
  98.  * Results:
  99.  *    A malloc'ed buffer containing the data.
  100.  *
  101.  * Side effects:
  102.  *    None.
  103.  *
  104.  *----------------------------------------------------------------------
  105.  */
  106.  
  107. char *
  108. LfsSegFetchBlock(segPtr, blockOffset, size)
  109.     LfsSeg        *segPtr;
  110.     int        blockOffset;
  111.     int        size;
  112. {
  113.     char *buf;
  114.     int      startAddr;
  115.  
  116.     startAddr = LfsSegStartAddr(segPtr) + LfsSegSizeInBlocks(segPtr->lfsPtr) - 
  117.             blockOffset - size/LfsBlockSize(segPtr->lfsPtr);
  118.  
  119.     buf = malloc(size);
  120.  
  121.     if (LfsDiskRead(segPtr->lfsPtr, startAddr , size, buf) != size) {
  122.     fprintf(stderr,"%s:LfsSegFetchBlock: Can't read seg %d offset %d.\n",
  123.         segPtr->lfsPtr->deviceName, segPtr->segNo, blockOffset);
  124.     return (char *) NULL;
  125.     }
  126.     return buf;
  127. }
  128.  
  129.  
  130. /*
  131.  *----------------------------------------------------------------------
  132.  *
  133.  * LfsSegReleaseBlock --
  134.  *
  135.  *    Release the memory allocated by LfsFetchBlock.
  136.  *
  137.  * Results:
  138.  *    None
  139.  *
  140.  * Side effects:
  141.  *    None.
  142.  *
  143.  *----------------------------------------------------------------------
  144.  */
  145.  
  146. void
  147. LfsSegReleaseBlock(segPtr, memPtr)
  148.     LfsSeg        *segPtr;
  149.     char    *memPtr;
  150. {
  151.     free(memPtr);
  152. }
  153.  
  154.  
  155. /*
  156.  *----------------------------------------------------------------------
  157.  *
  158.  * LfsSegRelease --
  159.  *
  160.  *    Release the initialize segment.
  161.  *
  162.  * Results:
  163.  *    None
  164.  *
  165.  * Side effects:
  166.  *    None.
  167.  *
  168.  *----------------------------------------------------------------------
  169.  */
  170.  
  171. void
  172. LfsSegRelease(segPtr)
  173.     LfsSeg        *segPtr;
  174. {
  175.     free((char *) segPtr);
  176. }
  177.  
  178.  
  179. static LfsSeg *CreateSegmentToWrite _ARGS_((Lfs *lfsPtr, Boolean dontBlock));
  180. static LfsSeg *GetSegStruct _ARGS_((Lfs *lfsPtr, LfsSegLogRange 
  181.             *segLogRangePtr, int startBlockOffset));
  182. static void AddNewSummaryBlock _ARGS_((LfsSeg *segPtr));
  183. static ReturnStatus WriteSegment _ARGS_((LfsSeg *segPtr));
  184. static void DestorySegStruct _ARGS_((LfsSeg *segPtr));
  185. static void CopySegToBuffer _ARGS_((LfsSeg *segPtr, int maxSize, 
  186.             char *bufferPtr, int *lenPtr));
  187. static void DoWriteDoneCalls _ARGS_((LfsSeg *segPtr, int flags));
  188.  
  189. static Boolean LayoutNewSeg _ARGS_((LfsSeg *segPtr, char *checkPointPtr, 
  190.         int *sizePtr));
  191.  
  192. static void RewindCurPtrs _ARGS_((LfsSeg *segPtr));
  193. static void FreeSegmentMem _ARGS_((LfsSeg *segPtr));
  194. static void InitSegmentMem _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr));
  195.  
  196. /*
  197.  * Macro returning TRUE if segment is completely empty.
  198.  */
  199. #define SegIsEmpty(segPtr) (((segPtr)->numBlocks == 1) &&         \
  200.         ((segPtr)->curSegSummaryPtr->size == sizeof(LfsSegSummary)))
  201.  
  202.  
  203. /*
  204.  *----------------------------------------------------------------------
  205.  *
  206.  * LfsSegSlowGrowSummary --
  207.  *
  208.  *    Insure that there is enought room for an object with the 
  209.  *    specified number of blocks and summary bytes. Possibly add a
  210.  *    new summary block if needed.
  211.  *
  212.  * Results:
  213.  *    A pointer to the summary bytes for this region or NIL if
  214.  *    there is not enought room.
  215.  *
  216.  * Side effects:
  217.  *
  218.  *----------------------------------------------------------------------
  219.  */
  220.  
  221. char *
  222. LfsSegSlowGrowSummary(segPtr, dataBlocksNeeded, sumBytesNeeded, addNewBlock)
  223.     register LfsSeg    *segPtr;    /* Segment of interest. */
  224.     int     dataBlocksNeeded;        /* Number of data blocks needed. */
  225.     int    sumBytesNeeded;            /* Number of summary bytes needed. */
  226.     Boolean addNewBlock;        /* Added a new block if necessary. */
  227. {
  228.     Lfs    *lfsPtr;
  229.     int     sumBytesLeft, blocksLeft, sumBlocks;
  230.  
  231.     /*
  232.      * Test the most common case first. Do the data and summary fit
  233.      * in the current configuration. 
  234.      */
  235.     sumBytesLeft = LfsSegSummaryBytesLeft(segPtr);
  236.     blocksLeft = LfsSegBlocksLeft(segPtr);
  237.     if ((blocksLeft >= dataBlocksNeeded) && (sumBytesLeft >= sumBytesNeeded)) {
  238.        return segPtr->curSummaryPtr;
  239.     }
  240.     /*
  241.      * Need to add a summary block. Bail if the user doesn't what it 
  242.      * or there is not enought room.
  243.      */
  244.     sumBlocks = 1;
  245.     if (!addNewBlock || (dataBlocksNeeded + sumBlocks > blocksLeft)) { 
  246.     return (char *) NIL;
  247.     }
  248.     lfsPtr = segPtr->lfsPtr;
  249.     /*
  250.      * Malloc a new summary buffer and add it to the segment.
  251.      */
  252.     AddNewSummaryBlock(segPtr);
  253.     return segPtr->curSummaryPtr;
  254. }
  255.  
  256.  
  257. /*
  258.  *----------------------------------------------------------------------
  259.  *
  260.  * LfsSegSlowDiskAddress --
  261.  *
  262.  *    Compute the disk address of a LfsSegElement.
  263.  *
  264.  * Results:
  265.  *    The disk address of the element.
  266.  *
  267.  * Side effects:
  268.  *    None.
  269.  *
  270.  *----------------------------------------------------------------------
  271.  */
  272.  
  273. int
  274. LfsSegSlowDiskAddress(segPtr, segElementPtr)
  275.     register LfsSeg    *segPtr;     /* Segment of interest. */
  276.     LfsSegElement *segElementPtr; /* Segment element of interest. */
  277. {
  278.     int    elementNumber, blockOffset;
  279.     int diskAddress, newDiskAddr;
  280.     /*
  281.      * Check the common case that we are asking about the "current"
  282.      * element. 
  283.      */
  284.     elementNumber = segElementPtr - segPtr->segElementPtr;
  285.  
  286.     if (elementNumber == segPtr->curElement) {
  287.     blockOffset = segPtr->curBlockOffset;
  288.     } else {
  289.     int    i;
  290.     blockOffset = segPtr->startBlockOffset;
  291.     for (i = 0; i <= elementNumber; i++) {
  292.         blockOffset += segPtr->segElementPtr[i].lengthInBlocks;
  293.     }
  294.     }
  295.     diskAddress = LfsSegNumToDiskAddress(segPtr->lfsPtr, segPtr->logRange.current);
  296.  
  297.     blockOffset = LfsSegSizeInBlocks(segPtr->lfsPtr) - blockOffset;
  298.     newDiskAddr = diskAddress + blockOffset;
  299.     return newDiskAddr;
  300. }
  301.  
  302. /*
  303.  *----------------------------------------------------------------------
  304.  *
  305.  * LfsSegSlowAddDataBuffer --
  306.  *
  307.  *    Add a LfsSegElement to a segment.
  308.  *
  309.  * Results:
  310.  *    A pointer to the LfsSegElement added. NIL if the object would not
  311.  *    fit.
  312.  *
  313.  * Side effects:
  314.  *    None.
  315.  *
  316.  *----------------------------------------------------------------------
  317.  */
  318.  
  319. LfsSegElement *
  320. LfsSegSlowAddDataBuffer(segPtr, blocks, bufferPtr, clientData)
  321.     register LfsSeg    *segPtr;  /* Segment to add to. */ 
  322.     int            blocks;      /* Size of buffer to add in blocks */
  323.     char   *bufferPtr;      /* Buffer to add. */
  324.     ClientData clientData; /* ClientData associated with this field. */
  325. {
  326.     LfsSegElement *elementPtr;
  327.  
  328.     if (segPtr->curBlockOffset + blocks > segPtr->curDataBlockLimit) {
  329.     return (LfsSegElement *) NIL;
  330.     }
  331.     segPtr->curElement++;
  332.     segPtr->curBlockOffset += blocks;
  333.  
  334.     elementPtr = segPtr->segElementPtr + segPtr->curElement;
  335.     elementPtr->lengthInBlocks = blocks;
  336.     elementPtr->clientData = clientData;
  337.     elementPtr->address    = bufferPtr;
  338.     segPtr->numElements = segPtr->curElement+1;
  339.     segPtr->numBlocks += blocks;
  340.     return elementPtr;
  341. }
  342.  
  343.  
  344. /*
  345.  *----------------------------------------------------------------------
  346.  *
  347.  * AddNewSummaryBlock --
  348.  *
  349.  *  Add a summary block to a segment.
  350.  *
  351.  * Results:
  352.  *    None.
  353.  *
  354.  * Side effects:
  355.  *    A new summary block is malloc() and initialized.
  356.  *
  357.  *----------------------------------------------------------------------
  358.  */
  359. static void
  360. AddNewSummaryBlock(segPtr)
  361.     LfsSeg    *segPtr;    /* Seg to add block to. */
  362. {
  363.     LfsSegElement *sumBufferPtr;
  364.     LfsSegSummary *newSummaryPtr;
  365.     int          sumBytes;
  366.  
  367.     sumBytes = LfsBlockSize(segPtr->lfsPtr);
  368.     sumBufferPtr = LfsSegAddDataBuffer(segPtr, 1, malloc(sumBytes),
  369.                     (ClientData) NIL);
  370.     newSummaryPtr =  (LfsSegSummary *) sumBufferPtr->address;
  371.     newSummaryPtr->magic = LFS_SEG_SUMMARY_MAGIC;
  372.     newSummaryPtr->timestamp = LfsGetCurrentTimestamp(segPtr->lfsPtr);
  373.     newSummaryPtr->prevSeg = segPtr->logRange.prevSeg;
  374.     newSummaryPtr->nextSeg = segPtr->logRange.nextSeg;
  375.     newSummaryPtr->size = sizeof(LfsSegSummary);
  376.     newSummaryPtr->nextSummaryBlock = -1;
  377.  
  378.     if (segPtr->curSegSummaryPtr != (LfsSegSummary *) NIL) { 
  379.     /*
  380.      * This is not the first summary block in the segment.  Fixup the
  381.      * size of the last summary block and point it at the new one. 
  382.      */
  383.     segPtr->curSegSummaryPtr->size = segPtr->curSummaryPtr - 
  384.                     (char *) (segPtr->curSegSummaryPtr);
  385.     segPtr->curSegSummaryPtr->nextSummaryBlock = segPtr->curBlockOffset;
  386.     } 
  387.     segPtr->curSegSummaryPtr = newSummaryPtr;
  388.  
  389.     segPtr->curSummaryPtr = sumBufferPtr->address + sizeof(LfsSegSummary);
  390.     segPtr->curSummaryLimitPtr = sumBufferPtr->address + sumBytes;
  391.     segPtr->lfsPtr->pstats.writeSummaryBlock++;
  392. }
  393.  
  394.  
  395. /*
  396.  *----------------------------------------------------------------------
  397.  *
  398.  * CreateSegmentToWrite --
  399.  *
  400.  *    Create an LfsSeg structure describing an empty segment to be 
  401.  *    filled in by the callback routines.
  402.  *
  403.  * Results:
  404.  *    A pointer to a lfsSeg.
  405.  *
  406.  * Side effects:
  407.  *    None.
  408.  *
  409.  *----------------------------------------------------------------------
  410.  */
  411. static LfsSeg *
  412. CreateSegmentToWrite(lfsPtr, dontBlock) 
  413.     Lfs    *lfsPtr;        /* For which file system. */
  414.     Boolean        dontBlock;    /* Don't wait for segment. */
  415. {
  416.     LfsSeg    *segPtr;
  417.     LfsSegLogRange    segLogRange;
  418.     int        startBlock;
  419.     ReturnStatus status;
  420.  
  421.     do { 
  422.     status = LfsGetLogTail(lfsPtr, dontBlock, &segLogRange, &startBlock);
  423.     if ((status == FS_WOULD_BLOCK) && !dontBlock) {
  424.         panic("Ran out of segments.");
  425.     } 
  426.     } while ((status == FS_WOULD_BLOCK) && !dontBlock);
  427.  
  428.     if (status == SUCCESS) { 
  429.     segPtr = GetSegStruct(lfsPtr, &segLogRange, startBlock);
  430.     } else {
  431.     segPtr = (LfsSeg *) NIL;
  432.     }
  433.     return segPtr;
  434. }
  435.  
  436.  
  437. /*
  438.  *----------------------------------------------------------------------
  439.  *
  440.  * RewindCurPtrs --
  441.  *
  442.  *    Rewind the current pointers of a segment to the start of the first
  443.  *    segment.
  444.  *
  445.  * Results:
  446.  *    None.
  447.  *
  448.  * Side effects:
  449.  *    None.
  450.  *
  451.  *----------------------------------------------------------------------
  452.  */
  453. static void
  454. RewindCurPtrs(segPtr)
  455.     LfsSeg    *segPtr;
  456. {
  457.     segPtr->curSegSummaryPtr = (LfsSegSummary *) 
  458.                 (segPtr->segElementPtr[0].address);
  459.     segPtr->curSummaryHdrPtr = (LfsSegSummaryHdr *) 
  460.                 (segPtr->curSegSummaryPtr + 1);
  461.     segPtr->curElement = 1;
  462.  
  463.     segPtr->curBlockOffset = segPtr->startBlockOffset+1;
  464.     segPtr->curDataBlockLimit = segPtr->curSummaryHdrPtr->numDataBlocks;
  465.     segPtr->curSummaryPtr = (char *) (segPtr->curSummaryHdrPtr + 1);
  466.     segPtr->curSummaryLimitPtr = (char *) (segPtr->curSummaryHdrPtr) +
  467.             segPtr->curSummaryHdrPtr->lengthInBytes;
  468.  
  469. }
  470.  
  471. /*
  472.  *----------------------------------------------------------------------
  473.  *
  474.  * DestorySegStruct --
  475.  *
  476.  *    Destory an LfsSeg structure.
  477.  *
  478.  * Results:
  479.  *    None.
  480.  *
  481.  * Side effects:
  482.  *    None.
  483.  *
  484.  *----------------------------------------------------------------------
  485.  */
  486.  
  487. static void
  488. DestorySegStruct(segPtr)
  489.     LfsSeg    *segPtr;    /* Segment to Destory. */
  490. {
  491.  
  492.     FreeSegmentMem(segPtr);
  493.     free((char *) segPtr);
  494. }
  495.  
  496.  
  497. /*
  498.  *----------------------------------------------------------------------
  499.  *
  500.  * GetSegStruct --
  501.  *
  502.  *    Allocate an LfsSeg structure.
  503.  *
  504.  * Results:
  505.  *    A lfsSeg structure
  506.  *
  507.  * Side effects:
  508.  *    None.
  509.  *
  510.  *----------------------------------------------------------------------
  511.  */
  512.  
  513. static LfsSeg *
  514. GetSegStruct(lfsPtr, segLogRangePtr, startBlockOffset)
  515.     Lfs    *lfsPtr;    /* File system. */
  516.     LfsSegLogRange *segLogRangePtr; /* Log range of segment. */
  517.     int           startBlockOffset; /* Starting block offset into segment */
  518. {
  519.     LfsSeg    *segPtr;
  520.  
  521.     segPtr = (LfsSeg *) malloc(sizeof(LfsSeg));
  522.     InitSegmentMem(lfsPtr, segPtr);
  523.     segPtr->logRange = *segLogRangePtr;
  524.     segPtr->numElements = 0;
  525.     segPtr->numBlocks = 0;
  526.     segPtr->startBlockOffset = startBlockOffset;
  527.     segPtr->activeBytes = 0;
  528.     segPtr->curSegSummaryPtr = (LfsSegSummary *) NIL;
  529.     segPtr->curSummaryHdrPtr = (LfsSegSummaryHdr *) NIL;
  530.     segPtr->curElement = -1;
  531.     segPtr->curBlockOffset = segPtr->startBlockOffset;
  532.     segPtr->curDataBlockLimit = LfsSegSizeInBlocks(lfsPtr);
  533.     segPtr->curSummaryPtr = (char *) NIL;
  534.     segPtr->curSummaryLimitPtr = (char *) NIL;
  535.  
  536.     return segPtr;
  537. }
  538.  
  539.  
  540.  
  541. /*
  542.  *----------------------------------------------------------------------
  543.  *
  544.  * InitSegmentMem --
  545.  *
  546.  *    Initialize the memory used by a file systems segment code.
  547.  *
  548.  * Results:
  549.  *    None.
  550.  *
  551.  * Side effects:
  552.  *    LfsSeg memories allocated.
  553.  *
  554.  *----------------------------------------------------------------------
  555.  */
  556. static void
  557. InitSegmentMem(lfsPtr, segPtr)
  558.     Lfs    *lfsPtr;
  559.     LfsSeg    *segPtr;
  560. {
  561.     int        maxSegElementSize;
  562.  
  563.     /*
  564.      * Compute the maximum size of the seg element array. It can't be
  565.      * bigger than one element per block in segment.
  566.      */
  567.  
  568.     maxSegElementSize = LfsBytesToBlocks(lfsPtr,LfsSegSize(lfsPtr)) * 
  569.                     sizeof(LfsSegElement);
  570.     /*
  571.      * Fill in the fixed fields of the preallocated segments.
  572.      */
  573.     segPtr->lfsPtr = lfsPtr;
  574.     segPtr->segElementPtr = (LfsSegElement *) malloc(maxSegElementSize);
  575.     segPtr->memPtr = malloc(LfsSegSize(lfsPtr));
  576.  
  577. }
  578.  
  579. /*
  580.  *----------------------------------------------------------------------
  581.  *
  582.  * FreeSegmentMem --
  583.  *
  584.  *    Free the memory used by a file systems segment code.
  585.  *
  586.  * Results:
  587.  *    None.
  588.  *
  589.  * Side effects:
  590.  *    LfsSeg structures freed.
  591.  *
  592.  *----------------------------------------------------------------------
  593.  */
  594. static void
  595. FreeSegmentMem(segPtr)
  596.     LfsSeg    *segPtr;
  597. {
  598.     free(segPtr->memPtr);
  599.     free((char *)(segPtr->segElementPtr));
  600.  
  601. }
  602.  
  603.  
  604. /*
  605.  *----------------------------------------------------------------------
  606.  *
  607.  * LayoutNewSeg --
  608.  *
  609.  *    Fillin a new segment to be written as part of recovery.
  610.  *
  611.  * Results:
  612.  *
  613.  * Side effects:
  614.  *    None.
  615.  *
  616.  *----------------------------------------------------------------------
  617.  */
  618. static Boolean
  619. LayoutNewSeg(segPtr, checkPointPtr, sizePtr)
  620.     LfsSeg    *segPtr;
  621.     char        *checkPointPtr;    /* Checkpoint area to be filled in.*/
  622.     int            *sizePtr; /* Size of checkpoint buffer. */
  623. {
  624.     char    *summaryPtr, *endSummaryPtr;
  625.     Boolean full;
  626.     int          moduleType, startOffset, size;
  627.     LfsCheckPointRegion    *regionPtr;
  628.     int        newStartBlockOffset;
  629.     LfsCheckPointRegion    *segUsageCheckpointRegionPtr;
  630.  
  631.  
  632.     full = FALSE;
  633.     segUsageCheckpointRegionPtr = (LfsCheckPointRegion *) NIL;
  634.     for(moduleType = 0; moduleType < LFS_MAX_NUM_MODS; ) {
  635.       regionPtr = (LfsCheckPointRegion *) checkPointPtr;
  636.     summaryPtr = LfsSegSlowGrowSummary(segPtr, 1,
  637.             sizeof(LfsSegSummaryHdr) + 16, TRUE);
  638.     if (summaryPtr == (char *) NIL) {
  639.         full = TRUE;
  640.         break;
  641.     }
  642.     segPtr->curSummaryHdrPtr = (LfsSegSummaryHdr *)  summaryPtr;
  643.     LfsSegSetSummaryPtr(segPtr, summaryPtr + sizeof(LfsSegSummaryHdr));
  644.     startOffset = segPtr->curBlockOffset;
  645.     size = 0;
  646.     switch (moduleType) {
  647.     case LFS_SEG_USAGE_MOD:
  648.         full = LfsUsageCheckpoint(segPtr, (char *)(regionPtr + 1),
  649.                  &size);
  650.          break;
  651.     case LFS_DESC_MAP_MOD:
  652.         full = LfsDescMapCheckpoint(segPtr,  (char *)(regionPtr + 1),
  653.                  &size);
  654.          break;
  655.     case LFS_FILE_LAYOUT_MOD:
  656.         full = LfsFileLayoutCheckpoint(segPtr, (char *)(regionPtr + 1),
  657.                 &size);
  658.          break;
  659.     default:
  660.         panic("Unknown module type %d\n", moduleType);
  661.     }
  662.     if (size > 0) {
  663.         if (moduleType == LFS_SEG_USAGE_MOD) {
  664.             segUsageCheckpointRegionPtr = regionPtr;
  665.         }
  666.         regionPtr->type = moduleType;
  667.         regionPtr->size = size + sizeof(LfsCheckPointRegion);
  668.         *sizePtr += regionPtr->size;
  669.         checkPointPtr += regionPtr->size;
  670.     }
  671.      endSummaryPtr = LfsSegGetSummaryPtr(segPtr); 
  672.      if ((startOffset != segPtr->curBlockOffset) ||
  673.          ((summaryPtr + sizeof(LfsSegSummaryHdr)) != endSummaryPtr)) {
  674.         segPtr->curSummaryHdrPtr->moduleType = moduleType;
  675.         segPtr->curSummaryHdrPtr->lengthInBytes = endSummaryPtr - 
  676.                 (char *) summaryPtr;
  677.         segPtr->curSummaryHdrPtr->numDataBlocks =  
  678.                 segPtr->curBlockOffset - startOffset;
  679.      } else {
  680.          LfsSegSetSummaryPtr(segPtr, summaryPtr);
  681.      }
  682.      if (full) { 
  683.         if (LfsSegSummaryBytesLeft(segPtr) > 16) {
  684.         break;
  685.         }
  686.      } else {
  687.         moduleType++;
  688.      }
  689.     }
  690.    /*
  691.     * Update the size of the last summary block and cap off this segment. 
  692.     */
  693.    segPtr->curSegSummaryPtr->size = segPtr->curSummaryPtr - 
  694.                     (char *) segPtr->curSegSummaryPtr;
  695.    newStartBlockOffset = -1;
  696.    if (!full) {
  697.     if (SegIsEmpty(segPtr)) { 
  698.         /*
  699.          * The segment is totally empty.  We don't need to write
  700.          * this one yet.
  701.          */
  702.         LFS_STATS_INC(segPtr->lfsPtr->stats.log.emptyWrites);
  703.         newStartBlockOffset = segPtr->startBlockOffset;
  704.     } else if ((segPtr->curDataBlockLimit -  segPtr->curBlockOffset) > 
  705.                segPtr->lfsPtr->superBlock.usageArray.wasteBlocks) { 
  706.         /*
  707.          * If this is considered to be a partial segment write add the
  708.          * summary block we needed.
  709.          */
  710.         AddNewSummaryBlock(segPtr);
  711.         newStartBlockOffset = segPtr->curBlockOffset-1;
  712.         LFS_STATS_INC(segPtr->lfsPtr->stats.log.partialWrites);
  713.     }
  714.    }
  715.    LfsSetLogTail(segPtr->lfsPtr, &segPtr->logRange, newStartBlockOffset, 
  716.                     segPtr->activeBytes);  
  717.    if (segUsageCheckpointRegionPtr != (LfsCheckPointRegion *) NIL) {
  718.        LfsSegUsageCheckpointUpdate(segPtr->lfsPtr, 
  719.             (char *) (segUsageCheckpointRegionPtr + 1),
  720.             segUsageCheckpointRegionPtr->size - 
  721.                         sizeof(LfsCheckPointRegion));
  722.     }
  723.    return full;
  724. }
  725.  
  726.  
  727. /*
  728.  *----------------------------------------------------------------------
  729.  *
  730.  * DoWriteDoneCalls --
  731.  *
  732.  *    Perform the call backs that take segments as input.
  733.  *
  734.  * Results:
  735.  *    TRUE if the segment is full. False otherwise.
  736.  *
  737.  * Side effects:
  738.  *    None.
  739.  *
  740.  *----------------------------------------------------------------------
  741.  */
  742. static void
  743. DoWriteDoneCalls( segPtr, flags) 
  744.     LfsSeg    *segPtr;    /* Segment to fill in or out. */
  745.     int        flags;        /* Flags used during checkpoint. */
  746.  
  747. {
  748.     int    moduleType,  next;
  749.     char     *endSummaryBlockPtr;
  750.     LfsSegElement *bufferPtr;
  751.  
  752.     /*
  753.      * We're doing a pass over an existing segment such as during a
  754.      * cleaning IN phase or a WRITE_DONE callback. Initialize the 
  755.      * moduleType from the summary region. 
  756.      */
  757.     endSummaryBlockPtr = (char *)segPtr->curSegSummaryPtr + 
  758.             segPtr->curSegSummaryPtr->size;
  759.     while(1) { 
  760.     while (((char *)segPtr->curSummaryHdrPtr < endSummaryBlockPtr) &&
  761.             (segPtr->curSummaryHdrPtr->lengthInBytes > 0))  {
  762.         moduleType = segPtr->curSummaryHdrPtr->moduleType;
  763.         segPtr->curSummaryLimitPtr = ((char *)(segPtr->curSummaryHdrPtr) + 
  764.                 segPtr->curSummaryHdrPtr->lengthInBytes);
  765.         segPtr->curSummaryPtr = (char *) (segPtr->curSummaryHdrPtr + 1);
  766.         switch (moduleType) {
  767.         case LFS_SEG_USAGE_MOD:
  768.             LfsSegUsageWriteDone(segPtr, flags);
  769.              break;
  770.         case LFS_DESC_MAP_MOD:
  771.             LfsDescMapWriteDone(segPtr, flags);
  772.              break;
  773.         case LFS_FILE_LAYOUT_MOD:
  774.             LfsFileLayoutWriteDone(segPtr, flags);
  775.              break;
  776.         default:
  777.             panic("Unknown module type %d\n", moduleType);
  778.         }
  779.          segPtr->curBlockOffset += segPtr->curSummaryHdrPtr->numDataBlocks;
  780.          /*
  781.           * Skip to the next summary header. 
  782.           */
  783.          segPtr->curSummaryHdrPtr = 
  784.             (LfsSegSummaryHdr *) segPtr->curSummaryLimitPtr;
  785.      }
  786.      /*
  787.       * If we ran over the end of current summary block move on to 
  788.       * the next.
  789.       */
  790.       next = segPtr->curSegSummaryPtr->nextSummaryBlock;
  791.         /*
  792.          * Free up any memory we allocated during the layout
  793.          */
  794.         free((char *) segPtr->curSegSummaryPtr);
  795.           if (next == -1) {
  796.         /*
  797.          * No more summary bytes for this segment.
  798.          */
  799.         break;
  800.        }
  801.        bufferPtr = LfsSegGetBufferPtr(segPtr);
  802.        segPtr->curSegSummaryPtr = (LfsSegSummary *) bufferPtr->address;
  803.        segPtr->curSummaryHdrPtr = (LfsSegSummaryHdr *)
  804.                         (segPtr->curSegSummaryPtr + 1);
  805.        endSummaryBlockPtr = (char *)segPtr->curSegSummaryPtr + 
  806.             segPtr->curSegSummaryPtr->size;
  807.        bufferPtr++;
  808.        LfsSegSetBufferPtr(segPtr, bufferPtr);
  809.        segPtr->curBlockOffset = next;
  810.     }
  811.    return;
  812. }
  813.  
  814.  
  815.  
  816. /*
  817.  *----------------------------------------------------------------------
  818.  *
  819.  * LfsSegCheckPoint --
  820.  *
  821.  *    Call the checkpoint routines all the segment I/O modules.
  822.  *
  823.  * Results:
  824.  *    SUCCESS if everything when well.
  825.  *
  826.  * Side effects:
  827.  *    None.
  828.  *
  829.  *----------------------------------------------------------------------
  830.  */
  831.  
  832. ReturnStatus
  833. LfsSegCheckPoint(lfsPtr, checkPointPtr, checkPointSizePtr)
  834.     Lfs              *lfsPtr;        /* File system to checkpoint. */
  835.     char        *checkPointPtr;    /* Checkpoint area to be filled in.*/
  836.     int            *checkPointSizePtr; /* Size of checkpoint buffer. */
  837. {
  838.     Boolean    full = TRUE;
  839.     LfsSeg    *segPtr;
  840.     ReturnStatus    status= SUCCESS;
  841.  
  842.     while (full) {
  843.     segPtr = CreateSegmentToWrite(lfsPtr, 1);
  844.     *checkPointSizePtr = 0;
  845.  
  846.     full = LayoutNewSeg(segPtr,checkPointPtr, checkPointSizePtr);
  847.     status = WriteSegment(segPtr);
  848.     if (status != SUCCESS) {
  849.         panic("Can't write segment to log\n");
  850.     }
  851.     RewindCurPtrs(segPtr);
  852.     DoWriteDoneCalls(segPtr, 0);
  853.         DestorySegStruct(segPtr);
  854.     }
  855.     return status;
  856.  
  857. }
  858.  
  859.  
  860. /*
  861.  *----------------------------------------------------------------------
  862.  *
  863.  * WriteSegment --
  864.  *
  865.  *    Write a segment to the log.
  866.  *
  867.  * Results:
  868.  *    SUCCESS if write complete. The ReturnStatus otherwise.
  869.  *
  870.  * Side effects:
  871.  *    None.
  872.  *
  873.  *----------------------------------------------------------------------
  874.  */
  875. static ReturnStatus
  876. WriteSegment(segPtr) 
  877.     LfsSeg    *segPtr;    /* Segment to write. */
  878. {
  879.     Lfs    *lfsPtr = segPtr->lfsPtr;
  880.     int offset, len, count;
  881.     int  diskAddress;
  882.     static char *memPtr = (char *) NULL;
  883.  
  884.     if (SegIsEmpty(segPtr)) { 
  885.     /*
  886.      * The segment being written is empty so we don't have
  887.      * to write anytime. 
  888.      */
  889.     return SUCCESS;
  890.     }
  891.  
  892.     /*
  893.      * Compute the starting disk address of this I/O.
  894.      */
  895.     diskAddress = LfsSegNumToDiskAddress(lfsPtr, segPtr->logRange.current);
  896.     offset = LfsSegSizeInBlocks(lfsPtr)    - segPtr->curBlockOffset;
  897.     diskAddress += offset;
  898.  
  899.     segPtr->curElement = segPtr->numElements-1;
  900.     segPtr->curBlockOffset = 0;
  901.  
  902.  
  903.     if (memPtr == (char *) NULL) {
  904.     memPtr = malloc(LfsSegSize(lfsPtr));
  905.     }
  906.     CopySegToBuffer(segPtr, LfsSegSize(lfsPtr), memPtr, &len);
  907.  
  908.     count = LfsDiskWrite(lfsPtr, diskAddress, len, memPtr);
  909.     if (count != len) {
  910.     return FAILURE;
  911.     } else {
  912.     return SUCCESS;
  913.     }
  914.  
  915. }
  916.  
  917. /*
  918.  *----------------------------------------------------------------------
  919.  *
  920.  * CopySegToBuffer --
  921.  *
  922.  *    Copy a segment into a buffer.
  923.  *
  924.  * Results:
  925.  *    None.
  926.  *
  927.  * Side effects:
  928.  *    None.
  929.  *
  930.  *----------------------------------------------------------------------
  931.  */
  932.  
  933.  
  934. static void
  935. CopySegToBuffer( segPtr, maxSize, bufferPtr, lenPtr)
  936.     LfsSeg    *segPtr;
  937.     int        maxSize;
  938.     char    *bufferPtr;
  939.     int        *lenPtr;
  940. {
  941.     int bytes, offset;
  942.     LfsSegElement *elementPtr;
  943.     Boolean full;
  944.  
  945.     *lenPtr = 0;
  946.     offset = 0;
  947.     full = FALSE;
  948.     while ((segPtr->curElement >= 0) && !full) {
  949.     elementPtr = segPtr->segElementPtr + segPtr->curElement;
  950.     bytes = LfsBlocksToBytes(segPtr->lfsPtr, 
  951.         elementPtr->lengthInBlocks - segPtr->curBlockOffset);
  952.     if (*lenPtr + bytes > maxSize) {
  953.         /*
  954.          * Element doesn't fit in this buffer. 
  955.          */
  956.         if (*lenPtr == maxSize) {
  957.         offset = 0;
  958.         } else { 
  959.         offset = LfsBytesToBlocks(segPtr->lfsPtr,(maxSize - *lenPtr));
  960.         }
  961.         bytes = LfsBlocksToBytes(segPtr->lfsPtr, offset);
  962.         full = TRUE;
  963.     } 
  964.     if (segPtr->curBlockOffset == 0) { 
  965.         bcopy(elementPtr->address, bufferPtr + *lenPtr, bytes);
  966.     } else {
  967.         bcopy(elementPtr->address + 
  968.            LfsBlocksToBytes(segPtr->lfsPtr,segPtr->curBlockOffset),
  969.           bufferPtr + *lenPtr, bytes);
  970.     }
  971.     *lenPtr += bytes;
  972.     if (full) {
  973.         segPtr->curBlockOffset += offset;
  974.     } else {
  975.         segPtr->curElement--;
  976.         segPtr->curBlockOffset = 0;
  977.     }
  978.     }
  979. }
  980.  
  981.  
  982.